package com.study.spmongodb.wwj.thread2.char01;

import java.util.Optional;
import java.util.stream.IntStream;

/**
 * @author MI
 * @version 1.0
 * @date 2020/12/6 21:00
 */
public class WaitSet {
    private static final Object LOCK = new Object();

    private static void work() {
        synchronized (LOCK) {
            System.out.println("begin ....");
            try {
                System.out.println("thread will comming");
                LOCK.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("thread will out.");
        }
    }

    /**
     * 1所有对象都有一个wait set 用来存放调用了该对象wait方法之后进入block状态线程。
     * 2 线程notify之后，不一定得到执行。
     * 3 线程从wait set 中唤醒顺序不一定是FIFO。
     * 4 线程被获取后，必须重写获取锁。
     */
    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            work();
        }, "").start();
        Thread.sleep(1000);
        synchronized (LOCK) {
            //.IllegalMonitorStateException
            LOCK.notify();
        }

        Thread.sleep(2000);

        IntStream.range(1, 10)
                .forEach(i -> {
                    new Thread(() -> {
                        synchronized (LOCK) {
                            try {
                                Optional.of(Thread.currentThread().getName()
                                        + " will come to wait "
                                ).ifPresent(System.out::println);
                                LOCK.wait();
                                Optional.of(Thread.currentThread().getName()
                                        + " will leave to wait "
                                ).ifPresent(System.out::println);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }).start();
                });

        Thread.sleep(3000);
        IntStream.rangeClosed(1, 10).forEach(i -> {
            synchronized (LOCK) {
                LOCK.notify();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}
